home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Die Speccy' 97
/
Die Speccy' 97.iso
/
amiga_system
/
the_aminet
/
util
/
boot
/
bind_namesii.lha
/
AssignNode.c
next >
Wrap
C/C++ Source or Header
|
1995-09-14
|
6KB
|
294 lines
/* $Header: Src:Dcc/BindNames/rcs/AssignNode.c,v 1.5 1995/06/21 17:24:04 cmh Exp cmh $
*
* BindNamesII: Handy assign/path maker.
* Copyright (C) 1994-95 Magnus Holmgren <cmh@augs.se>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <exec/types.h>
#include <exec/memory.h>
#include <dos/exall.h>
#include <clib/alib_protos.h>
#include <clib/dos_protos.h>
#include <clib/exec_protos.h>
#include <clib/utility_protos.h>
#ifdef __GNUC__
#include <inline/dos.h>
#include <inline/exec.h>
#include <inline/utility.h>
#endif
#include <string.h>
#include "assignnode.h"
#define Prototype extern
#include "proto.h"
#include "macros.h"
#define ANSI_WHITE_ON "\x9b" "2m"
#define ANSI_WHITE_OFF "\x9b" "22m"
/* Duplicate a string. Use FreeVec() to free the duplicate. */
STRPTR
StrDup( STRPTR string )
{
STRPTR newString;
if( ( newString = AllocVec( strlen( string ) + 1, MEMF_ANY ) ) )
{
strcpy( newString, string );
}
return( newString );
}
/* Scans the specified list of AssignNodes after an AssignNode with
* the specified name. Case is ignored.
*/
Prototype struct AssignNode *FindAssignNode( struct MinList *, STRPTR );
struct AssignNode *
FindAssignNode( struct MinList *start, STRPTR name )
{
struct AssignNode *node, *next;
FOREACHNODE( start, node, next )
{
if( !Stricmp( node->Name, name ) )
{
break;
}
}
return( node->Node.mln_Succ ? node : NULL );
}
/* Simply free a PathNode. If NULL, do nothing. */
Prototype VOID FreePathNode( struct PathNode * );
VOID
FreePathNode( struct PathNode *node )
{
if( node )
{
FreeVec( node->Name );
FreeVec( node );
}
}
/* Create a PathNode with the specified name and priority. */
struct PathNode *
AllocPathNode( STRPTR name, BYTE pri )
{
struct PathNode *node;
if( ( node = AllocVec( sizeof( struct PathNode ), MEMF_CLEAR ) ) )
{
node->Node.ln_Pri = pri;
if( !( node->Name = StrDup( name ) ) )
{
FreeVec( node );
node = NULL;
}
}
return( node );
}
/* Simply free an AssignNode. If NULL, do nothing. */
Prototype VOID FreeAssignNode( struct AssignNode * );
VOID
FreeAssignNode( struct AssignNode *node )
{
if( node )
{
struct PathNode *pathNode, *next;
FOREACHNODE( &node->Path, pathNode, next )
{
FreePathNode( pathNode );
}
FreeVec( node->Alias );
FreeVec( node->Name );
FreeVec( node );
}
}
/* Create an AssignNode with the specified attributes. Scans the list for
* nodes with the same name. If found, the path targets will be added to
* the old node.
*/
Prototype struct AssignNode *AllocAssignNode( struct MinList *, STRPTR, STRPTR *, BYTE, STRPTR, WORD, WORD );
struct AssignNode *
AllocAssignNode(
struct MinList *list,
STRPTR name,
STRPTR *path,
BYTE pri,
STRPTR alias,
WORD type,
WORD flags )
{
struct AssignNode *assignNode;
/* Try to locate previous node */
assignNode = FindAssignNode( list, name );
if( assignNode || ( assignNode = AllocVec( sizeof( struct AssignNode ), MEMF_CLEAR ) ) )
{
struct PathNode *pathNode;
BOOL add = FALSE;
/* Adding to a previous node? */
if( !assignNode->Name )
{
/* Nope, init new list */
NewList( ( struct List * ) &( assignNode->Path ) );
add = TRUE;
if( !( assignNode->Name = StrDup( name ) ) )
{
goto error; /* This kind of goto:s can be accepted sometimes.. :) */
}
}
if( alias && !assignNode->Alias && !( assignNode->Alias = StrDup( alias ) ) )
{
goto error;
}
/* Add the targets */
for( ; *path; ++path )
{
if( ( pathNode = AllocPathNode( *path, pri ) ) )
{
Enqueue( ( struct List * ) &( assignNode->Path ),
( struct Node * ) pathNode );
}
else
{
goto error;
}
}
assignNode->AssignType = type;
assignNode->Flags |= flags;
if( add )
{
AddTail( ( struct List * ) list, ( struct Node * ) assignNode );
}
}
return( assignNode );
error: FreeAssignNode( assignNode );
return( NULL );
}
/* Free all nodes on the list, assuming they are AssignNodes. */
Prototype VOID FreeAssignList( struct MinList * );
VOID
FreeAssignList( struct MinList *list )
{
struct AssignNode *node, *next;
FOREACHNODE( list, node, next )
{
FreeAssignNode( node );
}
NewList( ( struct List * ) list );
}
/* Print the assinglist, in an Assign-like manner.
* Also prints any accumulated errors.
*/
Prototype VOID PrintAssignList( struct MinList * );
VOID
PrintAssignList( struct MinList *list )
{
struct AssignNode *node, *nextAssign;
struct PathNode *pathNode, *nextPath;
BOOL first;
FOREACHNODE( list, node, nextAssign )
{
STRPTR str;
/* Print assign name */
Printf( ( node->Flags & ANF_ADD ) ? "%-18s+ " : "%-20s", ( LONG ) node->Name );
first = TRUE;
/* Print the target(s) */
FOREACHNODE( &node->Path, pathNode, nextPath )
{
switch( node->AssignType )
{
case ASN_DEFER:
str = "<%s>\n";
break;
case ASN_PATH:
str = "[%s]\n";
break;
default:
str = first ? "%s\n" : "\t\t + %s\n";
}
Printf( str, ( LONG ) pathNode->Name );
first = FALSE;
}
/* Handle the errors. */
if( node->Flags & ( ANF_FAILED | ANF_LOOP | ANF_BAD | ANF_BADPARENT ) )
{
Printf( " " ANSI_WHITE_ON "Failed because: " );
if( node->Flags & ANF_FAILED )
{
PrintFault( node->IoErr, NULL );
}
else if( node->Flags & ANF_LOOP )
{
Printf( "part of an assign loop" );
}
else if( node->Flags & ANF_BADPARENT )
{
Printf( "parent assign failed" );
}
else
{
Printf( "bad assign (multiple targets for DEFER or PATH)" );
}
Printf( ANSI_WHITE_OFF "\n" );
}
}
}